<template>
  <div class="w-full">
    <el-form ref="formRef" :model="{ tableData }" :rules="formRules">
      <el-table :data="tableData" border stripe style="width: 100%">
        <!-- 操作列 -->
        <el-table-column v-if="config.showOperation" label="操作" :width="config.operationWidth || 120" fixed="left"
          align="center">
          <template #default="{ $index }">
            <el-button v-if="config.showAddBtn" type="primary" size="small" :icon="Plus" circle @click="addRow($index)"
              :disabled="isMaxRows" />
            <el-button v-if="config.showDeleteBtn" type="danger" size="small" :icon="Delete" circle
              @click="deleteRow($index)" :disabled="isMinRows" />
          </template>
        </el-table-column>

        <!-- 动态数据列 -->
        <el-table-column v-for="(column, colIndex) in config.columns" :key="column.prop" :label="column.label"
          :prop="column.prop" :width="column.width">
          <template #header>
            <span>
              <span v-if="column.required" class="required-star">*</span>
              {{ column.label }}
            </span>
          </template>

          <template #default="{ row, $index }">
            <el-form-item :prop="`tableData.${$index}.${column.prop}`" :rules="getColumnRules(column)"
              class="table-form-item">
              <!-- 输入框 -->
              <el-input v-if="column.type === 'input'" v-model="row[column.prop]"
                :placeholder="column.placeholder || `请输入${column.label}`" :disabled="column.disabled"
                :maxlength="column.maxlength" :show-word-limit="column.showWordLimit" clearable />

              <!-- 多行文本 -->
              <el-input v-else-if="column.type === 'textarea'" v-model="row[column.prop]" type="textarea"
                :placeholder="column.placeholder || `请输入${column.label}`" :disabled="column.disabled"
                :maxlength="column.maxlength" :show-word-limit="column.showWordLimit" :rows="2" />

              <!-- 数字输入框 -->
              <el-input-number v-else-if="column.type === 'number'" v-model="row[column.prop]"
                :placeholder="column.placeholder || `请输入${column.label}`" :disabled="column.disabled" :min="column.min"
                :max="column.max" :step="column.step || 1" :precision="column.precision" controls-position="right"
                style="width: 100%" />

              <!-- 下拉框 -->
              <el-select v-else-if="column.type === 'select'" v-model="row[column.prop]"
                :placeholder="column.placeholder || `请选择${column.label}`" :disabled="column.disabled"
                :multiple="column.multiple" clearable style="width: 100%">
                <el-option v-for="option in column.options" :key="option.value" :label="option.label"
                  :value="option.value" :disabled="option.disabled" />
              </el-select>

              <!-- 日期选择器 -->
              <el-date-picker v-else-if="column.type === 'date'" v-model="row[column.prop]" type="date"
                :placeholder="column.placeholder || `请选择${column.label}`" :disabled="column.disabled"
                :format="column.dateFormat || 'YYYY-MM-DD'" :value-format="column.valueFormat || 'YYYY-MM-DD'" clearable
                style="width: 100%" />

              <!-- 日期时间选择器 -->
              <el-date-picker v-else-if="column.type === 'datetime'" v-model="row[column.prop]" type="datetime"
                :placeholder="column.placeholder || `请选择${column.label}`" :disabled="column.disabled"
                :format="column.dateFormat || 'YYYY-MM-DD HH:mm:ss'"
                :value-format="column.valueFormat || 'YYYY-MM-DD HH:mm:ss'" clearable style="width: 100%" />

              <!-- 自定义插槽 -->
              <slot v-else-if="column.type === 'custom' && column.slotName" :name="column.slotName" :row="row"
                :index="$index" :column="column" />
            </el-form-item>
          </template>
        </el-table-column>

        <!-- 自定义额外列插槽 -->
        <slot name="extra-columns" />
      </el-table>
    </el-form>

    <!-- 底部操作栏插槽 -->
    <slot name="footer" :add-row="() => addRow(tableData.length)" />
  </div>
</template>

<script lang="ts" setup>
import { ref, computed, watch } from 'vue'
import { Plus, Delete } from '@element-plus/icons-vue'
import type { FormInstance, FormRules } from 'element-plus'
import type { DynamicTableConfig, ColumnConfig } from '../types/dynamicTable'

interface Props {
  config: DynamicTableConfig
  modelValue: any[]
  validateOnChange?: boolean // 是否实时校验
}

const props = withDefaults(defineProps<Props>(), {
  validateOnChange: false
})

const emit = defineEmits<{
  'update:modelValue': [value: any[]]
  'add': [index: number]
  'delete': [index: number, row: any]
  'change': [data: any[]]
}>()

const formRef = ref<FormInstance>()
const tableData = ref<any[]>([...props.modelValue])

// 监听外部数据变化
watch(() => props.modelValue, (newVal) => {
  tableData.value = [...newVal]
}, { deep: true })

// 监听内部数据变化
watch(tableData, (newVal) => {
  emit('update:modelValue', newVal)
  emit('change', newVal)
}, { deep: true })

// 计算是否达到最大/最小行数
const isMaxRows = computed(() => {
  return props.config.maxRows !== undefined && tableData.value.length >= props.config.maxRows
})

const isMinRows = computed(() => {
  return props.config.minRows !== undefined && tableData.value.length <= props.config.minRows
})

// 动态生成表单校验规则
const formRules = computed<FormRules>(() => {
  const rules: FormRules = {}
  props.config.columns.forEach(column => {
    if (column.required || column.rules) {
      // 为每一行的每个字段生成规则
      tableData.value.forEach((_, index) => {
        const fieldKey = `tableData.${index}.${column.prop}`
        rules[fieldKey] = getColumnRules(column)
      })
    }
  })
  return rules
})

// 获取列的校验规则
const getColumnRules = (column: ColumnConfig) => {
  const rules: any[] = []

  if (column.required) {
    rules.push({
      required: true,
      message: `${column.label}不能为空`,
      trigger: ['blur', 'change']
    })
  }

  if (column.rules) {
    rules.push(...column.rules)
  }

  return rules
}

// 创建空行
const createEmptyRow = () => {
  const row: any = {}
  props.config.columns.forEach(column => {
    row[column.prop] = column.type === 'number' ? undefined : ''
  })
  return row
}

// 添加行
const addRow = (index: number) => {
  if (isMaxRows.value) {
    return
  }
  const newRow = createEmptyRow()
  tableData.value.splice(index + 1, 0, newRow)
  emit('add', index)
}

// 删除行
const deleteRow = (index: number) => {
  if (isMinRows.value) {
    return
  }
  const deletedRow = tableData.value[index]
  tableData.value.splice(index, 1)
  emit('delete', index, deletedRow)
}

// 表单校验
const validate = async () => {
  if (!formRef.value) return false
  try {
    await formRef.value.validate()
    return true
  } catch (error) {
    return false
  }
}

// 重置表单
const resetFields = () => {
  formRef.value?.resetFields()
}

// 清空校验
const clearValidate = () => {
  formRef.value?.clearValidate()
}

// 获取表格数据
const getData = () => {
  return tableData.value
}

// 设置表格数据
const setData = (data: any[]) => {
  tableData.value = [...data]
}

// 暴露方法
defineExpose({
  validate,
  resetFields,
  clearValidate,
  getData,
  setData,
  addRow,
  deleteRow
})
</script>

<style scoped>
.required-star {
  color: var(--el-color-danger);
  margin-right: 4px;
}

.table-form-item {
  margin-bottom: 0;
}

/* 移除表单项的错误提示边距 */
:deep(.el-form-item__error) {
  position: static;
  padding-top: 2px;
}

/* 表格内的表单项样式优化 */
:deep(.el-form-item) {
  margin-bottom: 0 !important;
}

:deep(.el-table .cell) {
  padding: 8px 0;
}
</style>